package juc.scenarios.order;

import lombok.Getter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 高级电商订单异步处理系统演示
 * 包含异常处理、重试机制、超时控制等高级特性
 */
public class AdvancedOrderProcessingDemo {

    // 自定义线程池
    private static final ExecutorService ORDER_EXECUTOR = new ThreadPoolExecutor(
            6, 12, 60L, TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(2000),
            new ThreadFactory() {
                private final AtomicInteger threadNumber = new AtomicInteger(1);

                @Override
                public Thread newThread(Runnable r) {
                    Thread t = new Thread(r, "advanced-order-processor-" + threadNumber.getAndIncrement());
                    t.setDaemon(false);
                    return t;
                }
            },
            new ThreadPoolExecutor.CallerRunsPolicy()
    );

    public static void main(String[] args) {
        System.out.println("=== 高级电商订单异步处理系统演示 ===\n");

        AdvancedOrderService orderService = new AdvancedOrderService();

        // 模拟多个订单
        List<Order> orders = Arrays.asList(
                new Order("ORD-001", 1001L, 2999.99),
                new Order("ORD-002", 1002L, 1299.50),
                new Order("ORD-003", 1003L, 5999.00)
        );

        // 批量处理订单
        List<CompletableFuture<OrderResult>> futures = orders.stream()
                .map(order -> CompletableFuture.supplyAsync(() -> {
                    try {
                        return orderService.processOrder(order);
                    } catch (Exception e) {
                        System.err.println("订单处理异常：" + order.getOrderId() + " - " + e.getMessage());
                        return new OrderResult(order.getOrderId(), false, "处理失败：" + e.getMessage(), null);
                    }
                }, ORDER_EXECUTOR))
                .collect(ArrayList::new, ArrayList::add, ArrayList::addAll);

        // 等待所有订单处理完成
        CompletableFuture<Void> allOrders = CompletableFuture.allOf(
                futures.toArray(new CompletableFuture[0])
        );

        try {
            allOrders.get(30, TimeUnit.SECONDS);

            System.out.println("\n=== 所有订单处理完成 ===");

            // 统计结果
            long successCount = futures.stream()
                    .map(CompletableFuture::join)
                    .filter(OrderResult::isSuccess)
                    .count();

            long totalTime = futures.stream()
                    .map(CompletableFuture::join)
                    .mapToLong(result -> result.getProcessingTime())
                    .sum();

            System.out.println("总订单数：" + orders.size());
            System.out.println("成功订单：" + successCount);
            System.out.println("失败订单：" + (orders.size() - successCount));
            System.out.println("平均处理时间：" + (totalTime / orders.size()) + "ms");

        } catch (Exception e) {
            System.err.println("批量订单处理失败：" + e.getMessage());
        } finally {
            ORDER_EXECUTOR.shutdown();
        }
    }

    /**
     * 订单实体类
     */
    @Getter
    static class Order {
        // Getters
        private final String orderId;
        private final Long userId;
        private final Double amount;
        private final Long createTime;

        public Order(String orderId, Long userId, Double amount) {
            this.orderId = orderId;
            this.userId = userId;
            this.amount = amount;
            this.createTime = System.currentTimeMillis();
        }

    }

    /**
     * 订单处理结果
     */
    @Getter
    static class OrderResult {
        private final String orderId;
        private final boolean success;
        private final String message;
        private final Map<String, Object> details;

        private final long processingTime;

        public OrderResult(String orderId, boolean success, String message, Map<String, Object> details) {
            this.orderId = orderId;
            this.success = success;
            this.message = message;
            this.details = details;
            this.processingTime = details != null ? (Long) details.getOrDefault("totalTime", 0L) : 0L;
        }

        @Override
        public String toString() {
            return "OrderResult{orderId='" + orderId + "', success=" + success +
                    ", message='" + message + "', processingTime=" + processingTime + "ms}";
        }
    }

    /**
     * 高级订单服务
     */
    static class AdvancedOrderService {

        /**
         * 处理订单 - 包含异常处理和重试机制
         */
        public OrderResult processOrder(Order order) throws Exception {
            long startTime = System.currentTimeMillis();
            System.out.println("\n开始处理订单：" + order.getOrderId());

            Map<String, Object> details = new ConcurrentHashMap<>();

            try {
                // 1. 库存扣减（带重试）
                CompletableFuture<Boolean> inventoryFuture = processWithRetry(() -> {
                    return reduceInventory(order);
                }, 3, 500);

                // 2. 优惠券核销（带重试）
                CompletableFuture<String> couponFuture = processWithRetry(() -> {
                    return useCoupon(order);
                }, 2, 300);

                // 3. 积分计算（带超时控制）
                CompletableFuture<Integer> pointsFuture = CompletableFuture.supplyAsync(() -> {
                    return calculatePoints(order);
                }, ORDER_EXECUTOR).orTimeout(2, TimeUnit.SECONDS).exceptionally(ex -> {
                    System.err.println("积分计算超时：" + ex.getMessage());
                    return 0; // 超时返回0积分
                });

                // 4. 消息通知（带异常处理）
                CompletableFuture<Boolean> notificationFuture = CompletableFuture.supplyAsync(() -> {
                    return sendNotification(order);
                }, ORDER_EXECUTOR).handle((result, ex) -> {
                    if (ex != null) {
                        System.err.println("消息通知异常：" + ex.getMessage());
                        return false; // 异常时返回false但不影响主流程
                    }
                    return result;
                });

                // 5. 风控检查（串行执行）
                CompletableFuture<Boolean> riskCheckFuture = CompletableFuture.supplyAsync(() -> {
                    return performRiskCheck(order);
                }, ORDER_EXECUTOR).thenCompose(riskResult -> {
                    if (riskResult) {
                        // 风控通过，继续后续检查
                        return CompletableFuture.supplyAsync(() -> {
                            return performCreditCheck(order);
                        }, ORDER_EXECUTOR);
                    } else {
                        // 风控不通过，直接返回false
                        return CompletableFuture.completedFuture(false);
                    }
                });

                // 6. 日志记录（依赖前面操作的结果）
                CompletableFuture<Boolean> logFuture = CompletableFuture.allOf(
                        inventoryFuture, couponFuture, pointsFuture, notificationFuture, riskCheckFuture
                ).thenApplyAsync(v -> {
                    try {
                        Boolean inventoryResult = inventoryFuture.get();
                        String couponResult = couponFuture.get();
                        Integer pointsResult = pointsFuture.get();
                        Boolean notificationResult = notificationFuture.get();
                        Boolean riskCheckResult = riskCheckFuture.get();

                        details.put("inventoryReduced", inventoryResult);
                        details.put("couponUsed", couponResult);
                        details.put("pointsEarned", pointsResult);
                        details.put("notificationSent", notificationResult);
                        details.put("riskCheckPassed", riskCheckResult);

                        return recordLog(order, inventoryResult, couponResult,
                                pointsResult, notificationResult, riskCheckResult);
                    } catch (Exception e) {
                        System.err.println("日志记录失败：" + e.getMessage());
                        return false;
                    }
                }, ORDER_EXECUTOR);

                // 等待所有操作完成
                CompletableFuture<Void> allTasks = CompletableFuture.allOf(
                        inventoryFuture, couponFuture, pointsFuture, notificationFuture, riskCheckFuture, logFuture
                );

                // 设置总体超时
                allTasks.get(15, TimeUnit.SECONDS);

                // 检查风控结果
                Boolean riskCheckResult = riskCheckFuture.get();
                if (!riskCheckResult) {
                    return new OrderResult(order.getOrderId(), false, "风控检查未通过", details);
                }

                // 计算处理时间
                long endTime = System.currentTimeMillis();
                details.put("totalTime", endTime - startTime);

                // 判断整体成功状态
                boolean allSuccess = inventoryFuture.get() && notificationFuture.get() &&
                        logFuture.get() && pointsFuture.get() > 0;

                String message = allSuccess ? "订单处理成功" : "订单处理部分失败";

                return new OrderResult(order.getOrderId(), allSuccess, message, details);

            } catch (TimeoutException e) {
                throw new Exception("订单处理超时", e);
            } catch (Exception e) {
                throw new Exception("订单处理失败：" + e.getMessage(), e);
            }
        }

        /**
         * 带重试机制的异步处理
         */
        private <T> CompletableFuture<T> processWithRetry(Supplier<T> supplier, int maxRetries, long delayMillis) {
            return CompletableFuture.supplyAsync(() -> {
                int retryCount = 0;
                Exception lastException = null;

                while (retryCount < maxRetries) {
                    try {
                        return supplier.get();
                    } catch (Exception e) {
                        lastException = e;
                        retryCount++;

                        if (retryCount < maxRetries) {
                            System.out.println("操作失败，第" + retryCount + "次重试...");
                            try {
                                Thread.sleep(delayMillis);
                            } catch (InterruptedException ie) {
                                Thread.currentThread().interrupt();
                                throw new RuntimeException("重试被中断", ie);
                            }
                        }
                    }
                }

                throw new RuntimeException("操作失败，已重试" + maxRetries + "次", lastException);
            }, ORDER_EXECUTOR);
        }

        /**
         * 库存扣减
         */
        private boolean reduceInventory(Order order) {
            try {
                System.out.println("开始库存扣减...");
                Thread.sleep(800); // 模拟数据库操作

                // 模拟库存检查（随机失败）
                if (Math.random() > 0.3) { // 70%成功率
                    System.out.println("库存扣减成功");
                    return true;
                } else {
                    System.err.println("库存不足");
                    throw new RuntimeException("库存不足");
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException("库存扣减被中断", e);
            }
        }

        /**
         * 优惠券核销
         */
        private String useCoupon(Order order) {
            try {
                System.out.println("开始优惠券核销...");
                Thread.sleep(500); // 模拟API调用

                // 模拟优惠券使用（随机失败）
                if (Math.random() > 0.4) { // 60%成功率
                    String couponCode = "COUPON-" + (int) (Math.random() * 10000);
                    System.out.println("优惠券核销成功：" + couponCode);
                    return couponCode;
                } else {
                    System.err.println("优惠券已过期或无效");
                    throw new RuntimeException("优惠券无效");
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException("优惠券核销被中断", e);
            }
        }

        /**
         * 积分计算
         */
        private int calculatePoints(Order order) {
            try {
                System.out.println("开始积分计算...");
                Thread.sleep(1500); // 模拟复杂计算（可能超时）

                // 模拟积分计算：订单金额的10%
                int points = (int) (order.getAmount() * 0.1);
                System.out.println("积分计算完成：" + points + "分");
                return points;
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return 0;
            }
        }

        /**
         * 消息通知
         */
        private boolean sendNotification(Order order) {
            try {
                System.out.println("开始消息通知...");
                Thread.sleep(600); // 模拟消息发送

                // 模拟消息发送（随机失败）
                if (Math.random() > 0.2) { // 80%成功率
                    System.out.println("消息通知成功");
                    return true;
                } else {
                    System.err.println("消息通知失败");
                    throw new RuntimeException("消息服务异常");
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException("消息通知被中断", e);
            }
        }

        /**
         * 风控检查
         */
        private boolean performRiskCheck(Order order) {
            try {
                System.out.println("开始风控检查...");
                Thread.sleep(1000); // 模拟风控检查

                // 模拟风控检查（随机失败）
                if (Math.random() > 0.1) { // 90%通过率
                    System.out.println("风控检查通过");
                    return true;
                } else {
                    System.err.println("风控检查未通过");
                    return false;
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return false;
            }
        }

        /**
         * 信用检查
         */
        private boolean performCreditCheck(Order order) {
            try {
                System.out.println("开始信用检查...");
                Thread.sleep(700); // 模拟信用检查

                // 模拟信用检查
                if (Math.random() > 0.15) { // 85%通过率
                    System.out.println("信用检查通过");
                    return true;
                } else {
                    System.err.println("信用检查未通过");
                    return false;
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return false;
            }
        }

        /**
         * 日志记录
         */
        private boolean recordLog(Order order, Boolean inventoryResult, String couponResult,
                                  Integer pointsResult, Boolean notificationResult, Boolean riskCheckResult) {
            try {
                System.out.println("开始日志记录...");
                Thread.sleep(200); // 模拟日志写入

                String logContent = String.format("订单[%s]处理完成：库存=%s, 优惠券=%s, 积分=%d, 通知=%s, 风控=%s",
                        order.getOrderId(), inventoryResult, couponResult, pointsResult, notificationResult, riskCheckResult);

                System.out.println("日志记录完成：" + logContent);
                return true;
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return false;
            }
        }
    }

    @FunctionalInterface
    interface Supplier<T> {
        T get() throws Exception;
    }
}